package com.freedom.start.shiro;

import com.freedom.start.sys.entity.UserEntity;
import com.freedom.start.sys.service.UserService;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.HashSet;
import java.util.Set;

/**
 * @Author: zhenggang.liu
 * @Date: 2019/8/9 9:57
 */

@Component
public class CustomRealm extends AuthorizingRealm {

    @Autowired
    private UserService userService;

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        Object principal = principalCollection.getPrimaryPrincipal();

        Set<String> roleSet = new HashSet<>();
        if ("admin".equals(principal)) {
            roleSet.add("admin");
        }

        if ("user".equals(principal)) {
            roleSet.add("user");
        }

        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(roleSet);
        return info;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        String clazz = Thread.currentThread().getStackTrace()[1].getClassName();
        String method = Thread.currentThread().getStackTrace()[1].getMethodName();
        System.out.println("class name: " + clazz + ", Method Name: " + method);
        UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
        String username = token.getUsername();
        UserEntity userEntity = userService.getByUsername(username);
        if (userEntity == null) {
            throw new UnknownAccountException("用户名不正确");
        }
        if (userEntity.getPassword() == null || !userEntity.getPassword().equals(String.valueOf(token.getPassword()))) {
            throw new IncorrectCredentialsException("密码错误");
        }

        Object credentials = computePassword(String.valueOf(token.getPassword()), username);
        ByteSource credentialSalt = ByteSource.Util.bytes(username.getBytes());

        return new SimpleAuthenticationInfo(username, credentials, credentialSalt, getName());
    }


    /**
     * username作为salt，对密码进行加密
     *
     * @param plaintext 明文密码
     * @param username  用户名，在此作为salt值
     * @return 返回值模拟中从数据库中取出的用户的password
     */
    public SimpleHash computePassword(String plaintext, String username) {
        String hashAlgorithmName = "MD5";
        Object credentials = plaintext;
        Object salt = username;
        int hashIterations = 1024;

        return new SimpleHash(hashAlgorithmName, credentials, salt, hashIterations);
    }
}
